/**
 * 
 */
package server.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.servlet.http.HttpSession;
import forum.Forum;
import forum.Member;
import forum.Post;
import forum.Thread;
import server.ForumAPIService;

/**
 * @author Alon Segal
 *
 */
public class WebAdapter implements ForumAPIService {

	public static final int FRIEND_NOTIFY = 0x1;
	public static final int VIEWER_NOTIFY = 0x2;
	public static final int AUTHOR_NOTIFY = 0x4;
	
	private static WebAdapter instance = null;
	
	private HashMap<String, Integer> usersNotify;
	private HashMap<String, ArrayList<Post>> userPosts;
	private Controller controller;
	
	/**
	 * 
	 */
	private WebAdapter() {
		this.controller = new Controller(true);
		this.usersNotify = new HashMap<String, Integer>();
		this.userPosts = new HashMap<String, ArrayList<Post>>();
	}
	
	public static WebAdapter getInstance() {
		if (instance == null) {
			instance = new WebAdapter();
		}
		return instance;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#getFriends(javax.servlet.http.HttpSession)
	 */
	@Override
	public List<Member> getFriends(HttpSession session) {
		return this.controller.getFriendsOfUser((String)session.getAttribute("username"));
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#addFriend(javax.servlet.http.HttpSession, java.lang.String)
	 */
	@Override
	public int addFriend(HttpSession session, String friendName) {
		int res = this.controller.addUserFriend((String)session.getAttribute("username"), 
				friendName);
		if(res == 0) {
			return 1;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#removeFriend(javax.servlet.http.HttpSession, java.lang.String)
	 */
	@Override
	public int removeFriend(HttpSession session, String friendName) {
		int res = this.controller.removeUserFriend((String)session.getAttribute("username"), 
				friendName);
		if(res == 0) {
			return 1;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#registerUser(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public int registerUser(String username, String firstName, String lastName,
			String password, String email, String gender) {
		if(gender.isEmpty()) {
			return 0;
		}
		int res = this.controller.registerUser(username, firstName, lastName, password, email, gender.charAt(0));
		if(res == 0) {
			return 1;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#removeUser(java.lang.String)
	 */
	@Override
	public int removeUser(String username) {
		int res = this.controller.removeUser(username);
		if(res == 0) {
			return 1;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#login(java.lang.String, java.lang.String)
	 */
	@Override
	public int login(String username, String password) {
		int res = this.controller.login(username, password);
		if(res == 0) {
			//Set the user notify code to zero.
			this.usersNotify.put(username, 0);
			return 1;
		}
		return 0;
	}
	
	public void logout(String username) {
		this.controller.logoff(username);
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#isModerator(java.lang.String)
	 */
	@Override
	public boolean isModerator(String username) {
		return this.controller.isUserModerator(username);
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#getForums()
	 */
	@Override
	public List<Forum> getForums() {
		return this.controller.getForums();
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#addForum(java.lang.String)
	 */
	@Override
	public int addForum(String subject, String username) {
		
		int res = this.controller.addForum(subject, username);
		if(res >= 0) {
			return 1;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#removeForum(int)
	 */
	@Override
	public int removeForum(int forumID) {
		int res = this.controller.removeForumWeb(forumID);
		if(res == 0) {
			return 1;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#getThreads(int)
	 */
	@Override
	public List<Thread> getThreads(int ForumID) {
		return this.controller.getThreadsTopicsOfForum(ForumID);
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#getThreadsIds()
	 */
	@Override
	public List<Integer> getThreadsIds() {
		return this.controller.getThreadsIds();
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#addThread(java.lang.String, int, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public int addThread(String username, int ForumID, String subject,
			String content, String date) {
		int res = this.controller.addThread(ForumID, subject, content, username);
		if(res == 0) {
			return 1;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#removeThread(int)
	 */
	@Override
	public int removeThread(int ThreadID) {
		int res = this.controller.removeThreadWeb(ThreadID);
		if(res == 0) {
			return 1;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#addReply(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public int addReply(int PostIDreplyTo, String username, String subject,
			String content, String date) {
		//Check forum ID
		int res = this.controller.addPost(0, PostIDreplyTo, subject, content, username);
		if(res > 0) {
			Post added = controller.getPostByID(res);
			// Handle interactivation
			// Send message to friends
			List<Member> friends = this.controller.getFriendsOfUser(username);
			for (int i = 0; i < friends.size(); i++) {
				Integer curNotify = usersNotify.get(friends.get(i).getUsername());
				if(curNotify == null) {
					curNotify = 0;
					usersNotify.put(friends.get(i).getUsername(), curNotify);
				}
				usersNotify.put(friends.get(i).getUsername(), curNotify | FRIEND_NOTIFY);
			}
			
			// Send message to viewers
			List<String> viewers = this.controller.getViewersOfThread(PostIDreplyTo);
			for (int i = 0; i < viewers.size(); i++) {
				//check that the current viewer is not the posting user himself
				if(viewers.get(i).equals(username)) {
					continue;
				}
				//Notifies user that new post arrived
				Integer curNotify = usersNotify.get(viewers.get(i));
				if(curNotify == null) {
					curNotify = 0;
					usersNotify.put(viewers.get(i), curNotify);
				}
				usersNotify.put(viewers.get(i), curNotify | VIEWER_NOTIFY);
				//Adding the new post to the user post list
				ArrayList<Post> curPosts = userPosts.get(viewers.get(i));
				if(curPosts == null) {
					curPosts = new ArrayList<Post>();
					userPosts.put(viewers.get(i), curPosts);
				}
				curPosts.add(added);
				userPosts.put(username, curPosts);
				
			}
			
			// Send message to author
			Thread thread = this.controller.getThreadsOfTopic(username, PostIDreplyTo);
			Post toAdd = thread.getRoot();
			String author = toAdd.getAuthor();
			if (!author.equals(username)) {
				Integer curNotify = usersNotify.get(author);
				if(curNotify == null) {
					curNotify = 0;
					usersNotify.put(author, curNotify);
				}
				usersNotify.put(author, curNotify | AUTHOR_NOTIFY);
			}
			
			
			return 1;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#removeReply(int)
	 */
	@Override
	public int removeReply(int PostID) {
		int res = this.controller.removePostWeb(PostID);
		if(res == 0) {
			return 1;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#getThread(int)
	 */
	@Override
	public List<Post> getThread(int threadID) {
		return this.controller.getThread(threadID);
	}
	
	public List<Post> getThread(int threadID, String username) {
		this.controller.addViewerByName(username, threadID);
		return this.controller.getThread(threadID);
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#getPost(int)
	 */
	@Override
	public Post getPost(int PostID) {
		return this.controller.getPostByID(PostID);
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#editPost(int, java.lang.String)
	 */
	@Override
	public int editPost(int postID, String content) {
		int res = this.controller.editPostWeb(postID, content);
		if(res == 0) {
			return 1;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see server.ForumAPIService#getInfoAboutFriend(java.lang.String)
	 */
	@Override
	public Member getInfoAboutFriend(String friendName) {
		return this.controller.getInfoAboutFriend(friendName);
	}
	
	/**
	 * Returns user notifies and reset the notifies to 0.
	 * @param username the user name
	 * @return the notify code
	 */
	public int getUserNotifies(String username) {
		Integer val = usersNotify.get(username);
		if(val == null) {
			val = 0;
		}
		this.usersNotify.put(username, 0);
		return val;
	}
	
	/**
	 * Returns the posts of the user to update and set the posts to empty list.
	 * @param username
	 * @return the posts list
	 */
	public ArrayList<Post> getUserPosts(String username) {
		ArrayList<Post> val = userPosts.get(username);
		if(val == null) {
			val = new ArrayList<Post>();
		}
		this.userPosts.put(username, new ArrayList<Post>());
		return val;
	}

}
